#include "menu.h"
#include "oled.h"
#include "dinogame.h"
#include "control.h"
#include "delay.h"
#include "led.h"
#include "usart.h"
#include "json.h"
#include "dht11.h"
#include "oled.h"
#include "voice.h"
#include "fire.h"
#include "beep.h"
#include "HC_SR04.h"
#include "key.h"
#include "ui.h"
#include "AD.h"
//#include "rtc.h"
 
//RTC_DateTypeDef GetData;  //获取日期结构体
 
//RTC_TimeTypeDef GetTime;   //获取时间结构体
u8 temp = 0,humi = 0;   //全局变量
int led_status = 0;//灯状态 0灭 1亮
float distance = 0;
uint8_t KeyNum;
u8 key;
void init(void);
void temperatureAndHumidityCheck(void);
void fireCheck(void);
void voiceCheck(void);
void jsonTransmission(void);
void acousticRanging(void);
void musicCheck(void);
 

void (*current_operation_index)();	 
 
Menu_table  table[20]=
{
    {0,0,0,1,0,(*home)},	//一级界面（主页面） 索引, 向下一个, 向下一个, 确定, 退出
		
    {1,8,2,9,0,(*Temperature)},	//二级界面 温湿度
    {2,1,3,10,0,(*Palygame)},			//二级界面 游戏
		{3,2,4,11,0,(*Fire)},					//二级界面 火焰
		{4,3,5,12,0,(*Distance)},			//二级界面 超声波测距
		{5,4,6,13,0,(*Voice)},				//二级界面 声音
    {6,5,7,14,0,(*Setting)},			//二级界面 设置
		{7,6,8,15,0,(*Test)},					//二级界面 test
    {8,7,1,16,0,(*Info)},					//二级界面 信息
		
		{9,9,9,9,1,(*TestTemperature)},				//三级界面：DHT11测量温湿度
		{10,10,10,10,2,(*ConrtolGame)},				//三级界面：谷歌小恐龙Dinogame
		{11,11,11,11,3,(*TestFire)},					//三级界面：测量火焰
		{12,12,12,12,4,(*TestDistance)},			//三级界面：超声波测距
		{13,13,13,13,5,(*TestVoice)},					//三级界面：测量声音
		{14,14,14,17,6,(*Set)},								//三级界面：设置普通外设状态 LED
		{15,15,15,15,7,(*TestTest)},					//三级界面;	test
		{16,16,16,16,8,(*Information)},				//三级界面：作者和相关项目信息
 
		{17,17,17,14,6,(*LEDInfo)},		//LED控制
};
 
u8  func_index = 0;	//主程序此时所在程序的索引值

/*
 * 菜单按键操作
*/
void  Menu_key_set(void)
{
	u8 key = KEY_Scan();
  if((key == 1) && (func_index != 10))
  { 
    func_index=table[func_index].next;	//按键next按下后的索引号
    OLED_Clear(); 
  }
	
  else if(((key == 2) && (func_index != 10)))
  {
    func_index=table[func_index].back;	//按键back按下后的索引号
    OLED_Clear(); 
  }
 
	else if(key == 3)
  {
		func_index=table[func_index].enter;	//按键enter按下后的索引号
    OLED_Clear();
  }
	
	else if(key == 4 && (func_index != 10))
  {
    func_index=table[func_index].previous;	//按键previous按下后的索引号
    OLED_Clear(); 
  }
	
  current_operation_index=table[func_index].current_operation;	//执行当前索引号所对应的功能函数
  (*current_operation_index)();//执行当前操作函数
}

/*
 * 是否显示状态栏 信号 蓝牙 电池
*/
void statusBar(u8 showSignal, u8 showBulethouch, u8 showWifi, u8 showEngery)
{
	if(showSignal)OLED_DrawBMP(0,0,20,3,signal_BMP);
	if(showBulethouch)OLED_DrawBMP(20,0,36,2,gImage_bulethouch);
	if(showWifi)OLED_DrawBMP(96,0,112,2,gImage_wifi);
	if(showEngery)OLED_DrawBMP(112,0,128,2,gImage_engery);
}
/*
 * 是否显示操作栏 菜单 确认 返回 左 右
*/
void actionBar(u8 showMenu, u8 showYes, u8 showBack, u8 showLeft, u8 showRight)
{
	if(showMenu)OLED_DrawBMP(4,6,20,8,gImage_menu);
	if(showYes)OLED_DrawBMP(4,6,20,8,gImage_yes);
	if(showBack)OLED_DrawBMP(107,6,123,8,gImage_back);
	if(showLeft)OLED_DrawBMP(12,4,28,6,gImage_left);
	if(showRight)OLED_DrawBMP(99,4,115,6,gImage_right);
}
/*
 * 一级主界面
 */
void home()
{
	//RTC_display();
	statusBar(1,1,1,1);
	OLED_DrawBMP(40,2,88,8,gImage_home);
	actionBar(1,0,1,0,0);
}
 /*
 * 二级界面 温湿度界面
 */
void Temperature()
{
	//RTC_display();
	statusBar(1,1,1,1);
	OLED_DrawBMP(40,2,88,8,gImage_temp);
	actionBar(0,1,1,1,1);
}
/*
 * 二级界面 游戏界面
 */
void Palygame()
{
	//RTC_display();
	statusBar(1,1,1,1);
	OLED_DrawBMP(40,2,88,8,gImage_playgame);
	actionBar(0,1,1,1,1);
}
/*
 * 二级界面 火焰界面
 */
void Fire()
{
	//RTC_display();
	statusBar(1,1,1,1);
	OLED_DrawBMP(40,2,88,8,gImage_fire);
	actionBar(0,1,1,1,1);
	
}
/*
 * 二级界面 距离界面
 */
void Distance()
{
	//RTC_display();
	statusBar(1,1,1,1);
	OLED_DrawBMP(40,2,88,8,gImage_distance);
	actionBar(0,1,1,1,1);
}
/*
 * 二级界面 声音测试
 */
void Voice()
{
	//RTC_display();
	statusBar(1,1,1,1);
	OLED_DrawBMP(40,2,88,8,gImage_vioce);
	actionBar(0,1,1,1,1);
}
/*
 * 二级界面 设置界面
 */
void Setting()
{
	//RTC_display();
	statusBar(1,1,1,1);
	OLED_DrawBMP(40,2,88,8,gImage_setting);
	actionBar(0,1,1,1,1);
}
/*
 * 二级界面 test界面
 */
void Test()
{
	//RTC_display();
	statusBar(1,1,1,1);
	OLED_DrawBMP(40,2,88,8,gImage_test);
	actionBar(0,1,1,1,1);
}
/*
* 二级界面 信息界面
*/
void Info()
{
	//RTC_display();
	statusBar(1,1,1,1);
	OLED_DrawBMP(40,2,88,8,gImage_info);
	actionBar(0,1,1,1,1);
}
/*
 * 三级界面 温湿度
 */
void TestTemperature()
{
	OLED_DrawBMP(12,2,28,6,gImage_temp_small);
	OLED_DrawBMP(12,4,28,6,gImage_humidity);
	OLED_ShowString(30, 2, "Tmp:", 16);
	OLED_ShowString(30, 4, "Hum:", 16);
	OLED_ShowString(80, 2, "'C", 16);
	OLED_ShowString(80, 4, "RH", 16);
	actionBar(0,0,1,0,0);
	temperatureAndHumidityCheck();
}
/*
 * 三级界面 开始游戏
 */
void ConrtolGame()
{
	Game_control();
	// 退出到主界面
	func_index=table[2].current;	//按键previous按下后的索引号
	OLED_Clear();
	current_operation_index=table[func_index].current_operation;	//执行当前索引号所对应的功能函数
	(*current_operation_index)();//执行当前操作函数
}
/*
 * 三级界面 火焰测试
 */
void TestFire()
{
	OLED_DrawBMP(12,2,44,6,gImage_fire_middle);
	OLED_ShowString(46, 3, "fire", 16);
	actionBar(0,0,1,0,0);
	fireCheck();
}
/*
 * 三级界面 距离测试
 */
void TestDistance()
{
	OLED_DrawBMP(12,2,44,6,gImage_measure);
	actionBar(0,0,1,0,0);
	acousticRanging();
}
/*
 * 三级界面 声音测试
 */
void TestVoice()
{
	OLED_DrawBMP(12,2,28,6,gImage_temp_small);
	actionBar(0,0,1,0,0);
	OLED_ShowString(30, 2, "voice:", 16);
	voiceCheck();
	GPIO_WriteBit(GPIO_LED_PORT, GPIO_Pin_15, Bit_RESET);
}
/*
 * 三级界面 设置
 */ 
void Set()
{
	OLED_ShowString(0,0,"Peripherals: Lights",16);
	OLED_ShowString(0,2,"Status: Closed",16);
	GPIO_WriteBit(GPIO_LED_PORT, GPIO_Pin_15, Bit_RESET);
}
/*
 * 三级界面 test
 */ 
void TestTest()
{
	OLED_ShowNum(0, 2, AD_Value[2], 4, 16);
	OLED_ShowNum(0, 4, AD_Value[3], 4, 16);
}
/*
 * 三级界面 信息
 */ 
void Information()
{
	//OLED_ShowString(0,0,"Author:YCH",16);
	//OLED_ShowString(0,2,"Date:2023/10/23",16);
	//OLED_ShowString(0,4,"Lab: IOTMonitor",16);
	//static int dino_dir = 0;
	
	//dino_dir % 2 == 0 ? dino_dir++ : 0;
	OLED_DrawBMP(10,2,30,5,FlyingDragon2[0]);
	OLED_DrawBMP(60,2,80,5,FlyingDragon2[1]);
	
}
/*
 * 四级界面 LED
 */
void LEDInfo()
{
	OLED_ShowString(0,0,"Peripherals: Lights",16);
	OLED_ShowString(0,2,"Status: Open",16);
	GPIO_WriteBit(GPIO_LED_PORT, GPIO_Pin_15, Bit_SET);
}

 /*
 *温湿度显示
*/
void temperatureAndHumidityCheck(void)
{
	if(DHT11_Read_Data(&temp,&humi)){    //&temp的地址对应*temp地址，所以数据一样
		//uint8_t Data[]= " ";             //创建目标数组，用来存放转换后的字符数据 
		//sprintf(Data,"%.3f",temp);       //保留小数点后3位小数，打印到Data数组中
		OLED_ShowNum(62,2,temp,2,16);	//显示温度
		OLED_ShowNum(62,4,humi,2,16);	//显示温度
		printf("{\"code\":%d,\"data\":{\"sn\":%s,\"name\":\"%s\",\"value\":{\"temp\":%d,\"humi\":%d},\"unit\":\"%s\",\"status\":%s},\"msg\":\"%s\"}", 200, "1001", "dht11", temp, humi, "C,RH", "true", "success");
	}
	else
		printf("{\"code\":%d,\"data\":{\"sn\":%s,\"name\":\"%s\",\"value\":%d,\"unit\":\"%s\",\"status\":%s},\"msg\":\"%s\"}", 200, "1001", "dht11", 0, "", "false", "EEROR! THE DHT11 HAS NO RESPOND...");
}
/*
 *超声波测距显示
*/
void acousticRanging(void)
{
	//pwmval=155;
  distance = Getlength();//获取距离长度
	//OLED_ShowNum(54,6,Length,3,16);	//显示温度
	//uint8_t Data[]= " ";                          //创建目标数组，用来存放转换后的字符数据 
  //sprintf(Data,"%.3f", distance);              //保留小数点后3位小数，打印到Data数组中
	OLED_ShowNum(46,3,distance,3,16);              //调用OLED字符串显示函数，在OLED屏上显示
	printf("{\"code\":%d,\"data\":{\"sn\":%s,\"name\":\"%s\",\"value\":%.3f,\"unit\":\"%s\",\"status\":%s},\"msg\":\"%s\"}", 200, "1003", "distance", distance, "mm", "true", "success");
}



/*
 *火焰传感器相关
 *如果检测到低电平则蜂鸣器报警
*/
void fireCheck(void)
{
	//while(GPIO_ReadInputDataBit(GPIO_FIRE_PORT,GPIO_FIRE_PIN) != 0){
	while(get_key()!=1 && GPIO_ReadInputDataBit(GPIO_FIRE_PORT,GPIO_FIRE_PIN) != 0){
		alarm();//否则就报警
		printf("{\"code\":%d,\"data\":{\"sn\":%s,\"name\":\"%s\",\"value\":%d,\"unit\":\"%s\",\"status\":%s},\"msg\":\"%s\"}", 200, "1004", "fire", 1, "", "true", "success");
	}
	//没有检测到低电平蜂鸣器不响
	GPIO_SetBits(GPIO_BEEP_PORT,GPIO_BEEP_PIN);
}
/*
 *声音传感器相关
*/
void voiceCheck(void)
{
	
	while(get_key()!=1 && VoiceSensor_Get() != 0){
		GPIO_WriteBit(GPIO_LED_PORT, GPIO_Pin_15, Bit_SET);
		printf("{\"code\":%d,\"data\":{\"sn\":%s,\"name\":\"%s\",\"value\":%d,\"unit\":\"%s\",\"status\":%s},\"msg\":\"%s\"}", 200, "1005", "distance", 1, "", "true", "success");
		delay_ms(1000);
	}
	GPIO_WriteBit(GPIO_LED_PORT, GPIO_Pin_15, Bit_RESET);
	

}

/*
 *数据传输相关
*/
void jsonTransmission(void)
{
	printf("{\"status\":none}");
	if(led_status == 1 && GPIO_ReadInputDataBit(GPIO_LED_PORT,GPIO_Pin_13) == 1)
	{
		LED=1;//亮灯
		printf("{\"status\":true}");
	}
	else if(led_status == 0 && GPIO_ReadInputDataBit(GPIO_LED_PORT,GPIO_Pin_13) == 0)
	{
		LED=0;//灭灯
		printf("{\"status\":false}");
	}
}

void RTC_display()				//RTC????
{
	  /*
	  // Get the RTC current Time 
	  HAL_RTC_GetTime(&hrtc, &GetTime, RTC_FORMAT_BIN);
    // Get the RTC current Date 
    HAL_RTC_GetDate(&hrtc, &GetData, RTC_FORMAT_BIN);
	
		// Display date Format : yy/mm/dd 
	
    // Display time Format : hh:mm:ss 
		OLED_ShowNum(40,0,GetTime.Hours,2,16);				//hour
		OLED_ShowString(57,0,":",16);	
		OLED_ShowNum(66,0,GetTime.Minutes,2,16);			//min
		OLED_ShowString(83,0,":",16);	
		OLED_ShowNum(93,0,GetTime.Seconds,2,16);			//seconds
	  */
}


